package com.globalwave.pos.inventory;

import java.util.ArrayList;

import org.junit.Test;

import com.globalwave.common.C;
import com.globalwave.common.exception.BusinessException;
import com.globalwave.pos.inventory.service.InventoryBO;
import com.globalwave.pos.inventory.service.InventoryBalanceBO;
import com.globalwave.pos.sale.entity.SalesOrder;
import com.globalwave.pos.sale.entity.SalesOrderLine;



import junit.framework.Assert;


public class InventoryBOTest extends InventoryBaseTestCase {


    private Long itemNumber = 12345L ;
    private String warehouseCode = "UTC1" ;
    private Long stockItemNumber1 = 12345L ;
    private Long stockItemNumber2 = 23456L ;
	
	@Test
	public void validateSalable_case1() throws Exception {
	    //Date d20110905000001 = new SimpleDateFormat("yyyyMMddHHmmss").parse("20110905000001") ;

	    SalesOrder order = new SalesOrder() ;
	    order.setWarehouse_code(warehouseCode) ;
	    order.setSale_date(20110905) ;
	    
	    SalesOrderLine line = new SalesOrderLine() ;
	    line.setSalesOrder(order) ;
	    line.setItem_number(itemNumber) ;
	    
	    
	    // item=12345,20110905后，可销售
		execute(getSqlFile(ItemMasterPriceBOTest.class)) ;
		
		execute(getSqlFile(ItemMasterPriceBOTest.class, "validateSalable_20110905")) ; 
		
		// 删除相关状态，不作状态检查
		execute(getSqlFile(ItemMasterStatusBOTest.class)) ;
		
        // 可销售量为95
		execute(getSqlFile(InventoryOnHandBalanceBOTest.class, "getSalableQuantity_Case2") ) ;
		
		InventoryBO bo = getInventoryBO() ;
		try {

		    line.setOrder_quantity(new Integer(94)) ;
		    bo.checkSalable(line) ;
		} catch (BusinessException e) {
			e.printStackTrace() ;
			Assert.assertTrue("d20110905000001 - BusinessException should not be throwed!", false) ;
		}
		
		try {
		    line.setOrder_quantity(new Integer(95)) ;
		    bo.checkSalable(line) ;
		} catch (BusinessException e) {
			Assert.assertTrue("d20110905000001 - BusinessException should not be throwed!", false) ;
			e.printStackTrace() ;
		}
		
		
		try {
		    line.setOrder_quantity(new Integer(96)) ;
		    bo.checkSalable(line) ;
			Assert.assertTrue("Over salable, BusinessException should be throwed!", false) ;
		} catch (BusinessException e) {
			Assert.assertEquals("err.inv.more.than.salable", e.getMessageKey()) ;
		}
		
		
		try {
		    line.setOrder_quantity(new Integer(-1)) ;
		    bo.checkSalable(line) ;
		    //bo.validateSalable(warehouseCode, itemNumber, null, new Integer(-1), d20110905000001) ;
			Assert.assertTrue("Over salable, BusinessException should be throwed!", false) ;
		} catch (BusinessException e) {
			Assert.assertEquals("err.inv.quantity.lt.0", e.getMessageKey()) ;
		}
	}
	
	/*

	@Test
	public void validateSalable_case11() throws Exception {
	    Date d20110905000001 = new SimpleDateFormat("yyyyMMddHHmmss").parse("20110905000001") ;

		execute(getSqlFile(this.getClass(), "validateSalable_case1")) ; 
		
	    // item=12345,20110905后，可销售
		execute(getSqlFile(ItemMasterPriceBOTest.class)) ;
		
		execute(getSqlFile(ItemMasterPriceBOTest.class, "validateSalable_20110905")) ; 
		
		// 删除相关状态，不作状态检查
		execute(getSqlFile(ItemMasterStatusBOTest.class)) ;
		
        // 可销售量为95
		execute(getSqlFile(InventoryOnHandBalanceBOTest.class, "getSalableQuantity_Case2") ) ;
		
		ItemBOImpl bo = getItemBO() ;
		//bo.setAccessor(accessor) ;
		try {
			ItemSO itemSO = new ItemSO() ;
			itemSO.setWarehouseCode(warehouseCode) ;
			itemSO.setItemNumber(itemNumber) ;
			itemSO.setItemQuantity(new Integer(94)) ;
			itemSO.setSaleDate(d20110905000001) ;
			
		    bo.retrieveItem(itemSO) ;
		} catch (BusinessException e) {
			Assert.assertTrue("d20110905000001 - BusinessException should not be throwed!", false) ;
			e.printStackTrace() ;
		}
		
		try {
			ItemSO itemSO = new ItemSO() ;
			itemSO.setWarehouseCode(warehouseCode) ;
			itemSO.setItemNumber(itemNumber) ;
			itemSO.setItemQuantity(new Integer(95)) ;
			itemSO.setSaleDate(d20110905000001) ;
			
		    bo.retrieveItem(itemSO) ;
		} catch (BusinessException e) {
			Assert.assertTrue("d20110905000001 - BusinessException should not be throwed!", false) ;
			e.printStackTrace() ;
		}
		
		
		try {
			ItemSO itemSO = new ItemSO() ;
			itemSO.setWarehouseCode(warehouseCode) ;
			itemSO.setItemNumber(itemNumber) ;
			itemSO.setItemQuantity(new Integer(96)) ;
			itemSO.setSaleDate(d20110905000001) ;
			
		    bo.retrieveItem(itemSO) ;
			Assert.assertTrue("Over salable, BusinessException should be throwed!", false) ;
		} catch (BusinessException e) {
			Assert.assertEquals("err.inv.more.than.salable", e.getMessageKey()) ;
		}
	}
*/

	@Test
	public void updateAndCancel() throws Exception {
		
		execute(getSqlFile(ItemMasterStatusBOTest.class, "validateSalable_20110905")) ;

		// ------------------- case 1
		InventoryBalanceBO balanceBO = getInventoryBalanceBO() ;
		balanceBO.setWarehouseCode(this.warehouseCode) ;
		
		Assert.assertEquals("case 1, item " + stockItemNumber1, new Integer(95), balanceBO.getSalableQuantity(stockItemNumber1)) ;
		Assert.assertEquals("case 1, item " + stockItemNumber2, new Integer(100), balanceBO.getSalableQuantity(stockItemNumber2)) ;
		
		// ------------------- case 2
		InventoryBO bo = getInventoryBO() ;
		bo.mortgage(order100000()) ;
		balanceBO.clear() ;
		
		Assert.assertEquals("case 2, item " + stockItemNumber1, new Integer(90), balanceBO.getSalableQuantity(stockItemNumber1)) ;
		Assert.assertEquals("case 2, item " + stockItemNumber1, new Integer(94), balanceBO.getSalableQuantity(stockItemNumber2)) ;
		
		// ------------------------- case 3
		try {
			bo.mortgage(order100001()) ;
			balanceBO.clear() ;
			Assert.assertTrue("case 3, order100001 Over salable, BusinessException should be throwed!", false) ;
		} catch (BusinessException e) {
			Assert.assertEquals("case 3", "err.inv.more.than.salable", e.getMessageKey()) ;
		}
		
		// ------------------------- case 4
		try {
			bo.mortgage(order100002()) ;
			balanceBO.clear() ;
			Assert.assertTrue("case 4, order100002 Over salable, BusinessException should be throwed!", false) ;
		} catch (BusinessException e) {
			Assert.assertEquals("case 4", "err.inv.more.than.salable", e.getMessageKey()) ;
		}
		

		
		// ------------------------- case 5
		bo.mortgage(order200000()) ;
		balanceBO.clear() ;
		
		Assert.assertEquals("case 5, item " + stockItemNumber1, new Integer(83), balanceBO.getSalableQuantity(stockItemNumber1)) ;
		Assert.assertEquals("case 5, item " + stockItemNumber2, new Integer(93), balanceBO.getSalableQuantity(stockItemNumber2)) ;
		
		
		// ------------------------- case 6
		bo.cancel(order100000()) ;
		balanceBO.clear() ;
		
		Assert.assertEquals("case 6, item " + stockItemNumber1, new Integer(88), balanceBO.getSalableQuantity(stockItemNumber1)) ;
		Assert.assertEquals("case 6, item " + stockItemNumber2, new Integer(99), balanceBO.getSalableQuantity(stockItemNumber2)) ;
		
		
		// ------------------------- case 7
		bo.shipment(shipment300000()) ;
		balanceBO.clear() ;
		
		Assert.assertEquals("case 7, item " + stockItemNumber1, new Integer(88), balanceBO.getSalableQuantity(stockItemNumber1)) ;
		Assert.assertEquals("case 7, item " + stockItemNumber2, new Integer(99), balanceBO.getSalableQuantity(stockItemNumber2)) ;
		
		
		// ------------------------- case 8
		bo.shipment(shipment400000()) ;
		balanceBO.clear() ;
		
		Assert.assertEquals("case 8, item " + stockItemNumber1, new Integer(88), balanceBO.getSalableQuantity(stockItemNumber1)) ;
		Assert.assertEquals("case 8, item " + stockItemNumber2, new Integer(99), balanceBO.getSalableQuantity(stockItemNumber2)) ;
		
		
		// ------------------------- case 9
		bo.cancel(order200000()) ;
		balanceBO.clear() ;
		
		Assert.assertEquals("case 9, item " + stockItemNumber1, new Integer(95), balanceBO.getSalableQuantity(stockItemNumber1)) ;
		Assert.assertEquals("case 9, item " + stockItemNumber2, new Integer(100), balanceBO.getSalableQuantity(stockItemNumber2)) ;
		
	}

	
	
	private SalesOrder order100000() {
		SalesOrder head = new SalesOrder() ;
		head.setWarehouse_code("UTC1") ;
		head.setOid(9100000L) ;
		head.setId(100000L) ;
		head.setType_(C.REF_SOURCE_SALES_ORDER) ;
		head.setSale_date(20110905) ;
		head.setLines(new ArrayList<SalesOrderLine>()) ;

		SalesOrderLine line = new SalesOrderLine() ;
		head.getLines().add(line) ;
		line.setSalesOrder(head) ;
		line.setSales_order_id(head.getOid()) ;
		line.setId(1000001L);
		line.setItem_number(stockItemNumber1) ;
		line.setOrder_quantity(5) ;
		

		line = new SalesOrderLine() ;
		head.getLines().add(line) ;
		line.setSalesOrder(head) ;
		line.setSales_order_id(head.getOid()) ;
		line.setId(1000002L);
		line.setItem_number(stockItemNumber2) ;
		line.setOrder_quantity(6) ;
		
		return head ;
	}

	
	private SalesOrder order100001() {
		SalesOrder head = new SalesOrder() ;
		head.setWarehouse_code("UTC1") ;
		head.setOid(9100001L) ;
		head.setId(100001L) ;
		head.setType_(C.REF_SOURCE_SALES_ORDER) ;
		head.setSale_date(20110905) ;
		head.setLines(new ArrayList<SalesOrderLine>()) ;

		SalesOrderLine line = new SalesOrderLine() ;
		head.getLines().add(line) ;
		line.setSalesOrder(head) ;
		line.setSales_order_id(head.getOid()) ;
		line.setId(1000011L);
		line.setItem_number(stockItemNumber1) ;
		line.setOrder_quantity(1) ;
		

		line = new SalesOrderLine() ;
		head.getLines().add(line) ;
		line.setSalesOrder(head) ;
		line.setSales_order_id(head.getOid()) ;
		line.setId(1000012L);
		line.setItem_number(stockItemNumber2) ;
		line.setOrder_quantity(100) ;
		
		return head ;
	}

	
	private SalesOrder order100002() {
		SalesOrder head = new SalesOrder() ;
		head.setWarehouse_code("UTC1") ;
		head.setOid(9100002L) ;
		head.setId(100002L) ;
		head.setType_(C.REF_SOURCE_SALES_ORDER) ;
		head.setSale_date(20110905) ;
		head.setLines(new ArrayList<SalesOrderLine>()) ;

		SalesOrderLine line = new SalesOrderLine() ;
		head.getLines().add(line) ;
		line.setSalesOrder(head) ;
		line.setSales_order_id(head.getOid()) ;
		line.setId(1000021L);
		line.setItem_number(stockItemNumber1) ;
		line.setOrder_quantity(100) ;
		

		line = new SalesOrderLine() ;
		head.getLines().add(line) ;
		line.setSalesOrder(head) ;
		line.setSales_order_id(head.getOid()) ;
		line.setId(1000022L);
		line.setItem_number(stockItemNumber2) ;
		line.setOrder_quantity(1) ;
		
		return head ;
	}
	
	private SalesOrder order200000() {
		SalesOrder head = new SalesOrder() ;
		head.setWarehouse_code("UTC1") ;
		head.setOid(9200000L) ;
		head.setId(200000L) ;
		head.setType_(C.REF_SOURCE_SALES_ORDER) ;
		head.setSale_date(20110905) ;
		head.setLines(new ArrayList<SalesOrderLine>()) ;

		SalesOrderLine line = new SalesOrderLine() ;
		head.getLines().add(line) ;
		line.setSalesOrder(head) ;
		line.setSales_order_id(head.getOid()) ;
		line.setId(2000001L);
		line.setItem_number(stockItemNumber1) ;
		line.setOrder_quantity(7) ;
		

		line = new SalesOrderLine() ;
		head.getLines().add(line) ;
		line.setSalesOrder(head) ;
		line.setSales_order_id(head.getOid()) ;
		line.setId(2000002L);
		line.setItem_number(stockItemNumber2) ;
		line.setOrder_quantity(1) ;
		
		return head ;
	}
	
	private SalesOrder shipment300000() throws Exception {
		SalesOrder order = order200000() ;
		order.setShipment_times((short)1) ;
		order.getLines().get(0).setShipped_quantity_1(1) ;
		order.getLines().get(0).setTna_quantity(0) ;
		order.getLines().get(1).setShipped_quantity_1(1) ;
		order.getLines().get(1).setTna_quantity(0) ;
		
		
		return order ;
	}
	
	private SalesOrder shipment400000() throws Exception {
		SalesOrder order = order200000() ;
		order.setShipment_times((short)2) ;
		//order.getLines().get(0).setShipped_quantity_1(1) ;
		order.getLines().get(0).setShipped_quantity_2(0) ;
		order.getLines().get(0).setTna_quantity(0) ;
		order.getLines().get(1).setShipped_quantity_2(6) ;
		order.getLines().get(1).setTna_quantity(0) ;
		
		
		return order ;
	}

	
	private InventoryBO getInventoryBO() {
		InventoryBO bo = (InventoryBO) appContext.getBean("inventoryBO") ;
		return bo ;
	}
	
	private InventoryBalanceBO getInventoryBalanceBO() {
		InventoryBalanceBO bo = (InventoryBalanceBO) appContext.getBean("inventoryBalanceBO") ;
		return bo ;
	}
}
